package gri_report_config;

use xml_helper;
use File::Basename;
use Data::Dumper;
use MIME::Base64;
use Cwd;

my $error="";

# validate_xml is actually a class sub rather than instance sub

sub validate_xml {
my $xml=shift;

	new("",undef,$xml);
	if($error eq "") {
		return undef;
	}
	return $error;
}

sub new {
my $self={};
shift;
my $f=shift;

	$error="";
	$self->{xml_helper}=new xml_helper();

	my $d=""; my $fd;
	if(defined($f)) {
		$self->{fullpath}=$f;
		if(!open($fd,$f)) {
			$error="Can not open file '$f' : $!";
			return(undef);
		}
		$d=join("",<$fd>);
		close($fd);
		my $fn=basename($f); $fn =~ s/\.xml//;
		$self->{filename}=$fn;
	} else {
		$d=shift;
		$self->{fullpath}=undef;
	}
	my $x=$self->{raw_xml}=$d;
	$x=$self->{xml_helper}->parse($d);
	if(! $x) {
		$error="Unable to parse XML!";
		return undef;
	}

	# Check the data is in the format we expect.

	my ($data,$attrs,$elements)=$self->{xml_helper}->get_element("");
	if(!defined($data)) {
		$error="Invalid data to parse [top level]";
		return(undef);
	}
	if(scalar(@$elements)!=1) {
		$error="More than 1 top level element!";
		return(undef);
	}
	if($elements->[0] ne "|report#0") {
		$error="Top level element is not 'report'";
		return(undef);
	}
	($data,$attrs,$elements)=$self->{xml_helper}->get_element("report#0");
	if(!defined($data)) {
		$error="Invalid data to parse [report#0]";
		return(undef);
	}
	#################################################################
	# We expect the title and reports elements to be here - abort	#
	# if not.							#
	#################################################################
	if(! grep {$_ eq "report#0|title#0"} @$elements) {
		$error="Missing 'title' element.";
		return(undef);
	}
	if(! grep {$_ eq "report#0|host#0"} @$elements) {
		$error="Missing 'host' element.";
		return(undef);
	}
	if(! grep {$_ eq "report#0|directory#0"} @$elements) {
		$error="Missing 'directory' element.";
		return(undef);
	}
	if(! grep {$_ eq "report#0|name#0"} @$elements) {
		$error="Missing 'name' element.";
		return(undef);
	}
	for my $cent (@$elements) {
		if(! grep {$_ eq $cent} (
			"report#0|title#0",
			"report#0|host#0",
			"report#0|directory#0",
			"report#0|type#0",
			"report#0|desc#0",
			"report#0|paging#0",
			"report#0|attributes#0",
			"report#0|display_name#0",
			"report#0|dynamic_convert_args#0",
			"report#0|dynamic_convert_type#0",
			"report#0|dynamic_convert_desc#0",
			"report#0|name#0")) {
			$error="Unexpected element '$cent' found.";
			return(undef);
		}
	}
	#################################################################
	# Get the data and store in the object for easy reference.	#
	#################################################################
	my ($data2,$attrs2,$elements2)=$self->{xml_helper}->get_element("report#0|title#0");
	$self->{title}=$data2;
	($data2,$attrs2,$elements2)=$self->{xml_helper}->get_element("report#0|host#0");
	$self->{host}=$data2;
	($data2,$attrs2,$elements2)=$self->{xml_helper}->get_element("report#0|directory#0");
	$self->{directory}=$data2;
	($data2,$attrs2,$elements2)=$self->{xml_helper}->get_element("report#0|name#0");
	$self->{name}=$data2;
	if(grep {$_ eq "report#0|desc#0"} @$elements) {
		($data2,$attrs2,$elements2)=$self->{xml_helper}->get_element("report#0|desc#0");
		$self->{desc}=decode_base64($data2);
	} else {
		$self->{desc}=undef;
	}
	if(grep {$_ eq "report#0|type#0"} @$elements) {
		($data2,$attrs2,$elements2)=$self->{xml_helper}->get_element("report#0|type#0");
		$self->{type}=$data2;
	} else {
		$self->{type}="html";
	}
	if(grep {$_ eq "report#0|attributes#0"} @$elements) {
		($data2,$attrs2,$elements2)=$self->{xml_helper}->get_element("report#0|attributes#0");
		$self->{attributes}=$data2;
	} else {
		$self->{attributes}="";
	}
	$self->{paging}=100;
	if(grep {$_ eq "report#0|paging#0"} @$elements) {
		($data2,$attrs2,$elements2)=$self->{xml_helper}->get_element("report#0|paging#0");
		$self->{paging}=$data2;
	}
	if(grep {$_ eq "report#0|display_name#0"} @$elements) {
		($data2,$attrs2,$elements2)=$self->{xml_helper}->get_element("report#0|display_name#0");
		$self->{display_name}=$data2;
	} else {
		$self->{display_name}=undef;
	}

	# Dynamic conversion options...
	if(grep {$_ eq "report#0|dynamic_convert_type#0"} @$elements) {
		($data2,$attrs2,$elements2)=$self->{xml_helper}->get_element("report#0|dynamic_convert_type#0");
		$self->{dynamic_convert_type}=$data2;
		$self->{dynamic_convert_args}="";
		$self->{dynamic_convert_desc}="";
		if(grep {$_ eq "report#0|dynamic_convert_args#0"} @$elements) {
			($data2,$attrs2,$elements2)=$self->{xml_helper}->get_element("report#0|dynamic_convert_args#0");
			$self->{dynamic_convert_args}=$data2;
		}
		if(grep {$_ eq "report#0|dynamic_convert_desc#0"} @$elements) {
			($data2,$attrs2,$elements2)=$self->{xml_helper}->get_element("report#0|dynamic_convert_desc#0");
			$self->{dynamic_convert_desc}=$data2;
		}
	} else {
		$self->{dynamic_convert_type}="";
		$self->{dynamic_convert_args}="";
		$self->{dynamic_convert_desc}="";
	}

	bless($self);
	return $self;
}

sub get_title {
my $self=shift;
	return $self->{title};
}

sub get_desc {
my $self=shift;
	return $self->{desc};
}

sub set_desc {
my $self=shift;
my $desc=shift;
	$self->{desc}=$desc;
}

sub set_title {
my $self=shift;
my $title=shift;
	$self->{title}=$title;
}

sub get_paging {
my $self=shift;
	return $self->{paging};
}

sub get_host {
my $self=shift;
	return $self->{host};
}

sub set_host {
my $self=shift;
my $host=shift;
	$self->{host}=$host;
}

# Notice that if the raw=>1 is set then we do not change %INST% to the
# web server installation directory, otherwise we keep in %INST% (for editing).

sub get_directory {
my $self=shift;
my %args=@_;

	my $x=$self->{directory};
	if($x !~ /\%INST\%/) {
		return $x;
	}
	if(exists($args{raw}) && $args{raw}) {
		return $x;
	}
	my $y=getcwd;
	$x =~ s/^\%INST\%[\/]{0,}/$y\//;
	return $x;
}

sub set_directory {
my $self=shift;
my $dir=shift;
	$self->{directory}=$dir;
}

sub get_attributes {
my $self=shift;
	if(!exists($self->{attributes})) {
		return "";
	}
	return $self->{attributes};
}

sub get_dynamic_info {
my $self=shift;
	return(
		$self->{dynamic_convert_type},
		$self->{dynamic_convert_args},
		$self->{dynamic_convert_desc}
	);
}

sub get_name {
my $self=shift;
	return $self->{name};
}

sub set_name {
my $self=shift;
my $name=shift;
	$self->{name}=$name;
}

sub get_type {
my $self=shift;

	if(!defined($self->{type}) || $self->{type} eq "") {
		return "html";
	}
	return $self->{type};
}

sub set_type {
my $self=shift;
my $type=shift;
	$self->{type}=$type;
}

sub get_display_name {
my $self=shift;

	return $self->{display_name};
}

sub set_display_name {
my $self=shift;
my $txt=shift;

	$self->{display_name}=$txt;
}

sub get_details {
my $self=shift;

	return ($self->{title},$self->{host},$self->{directory},$self->{name},$self->{display_name});
}

sub get_details2 {
my $self=shift;

	return {
		title => $self->{title},
		host => $self->{host},
		directory => $self->{directory},
		desc => $self->{desc},
		type => $self->{type},
		reptype => 'R',
		paging => $self->{paging},
		attributes => $self->{attributes},
		display_name => $self->{display_name},
		dynamic_convert_args => $self->{dynamic_convert_args},
		dynamic_convert_type => $self->{dynamic_convert_type},
		dynamic_convert_desc => $self->{dynamic_convert_desc},
		name => $self->{name},
		filename => $self->{filename},
	};
}

sub error {
	return $error;
}

sub get_xml {
my $self=shift;

	return $self->{raw_xml};
}

# If the file already exists it will be replaced, but initially
# write out the details to a temporary filename.

sub write_file() {
my $self=shift;
my $aa=$self->{xml_helper};

	my $fp=shift;
	if(!defined($fp)) {
		$fp=$self->{fullpath};
	}
	if(!defined($fp)) {
		return "No full path defined for file.";
	}
	open($wfd,">$fp.$$") or return "Failed to open temporary file: $!";
	my $str="<?xml version=\"1.0\" standalone=\"yes\"?>\n";
	$str.="<report>\n";
	$str.="\t<title>" . $aa->string_to_xml($self->{title}) . "</title>\n";
        $str.="\t<desc>" . encode_base64($self->{desc},'') . "</desc>\n";
        $str.="\t<host>" . $aa->string_to_xml($self->{host}) . "</host>\n";
        $str.="\t<directory>" . $aa->string_to_xml($self->{directory}) . "</directory>\n";
        $str.="\t<name>" . $aa->string_to_xml($self->{name}) . "</name>\n";
        $str.="\t<type>" . $aa->string_to_xml($self->{type}) . "</type>\n";
	if(exists($self->{paging}) && defined($self->{paging})) {
		$str.="\t<paging>" . $aa->string_to_xml($self->{paging}) . "</paging>\n";
	}
	if(exists($self->{display_name}) && defined($self->{display_name})) {
		$str.="\t<display_name>" . $aa->string_to_xml($self->{display_name}) . "</display_name>\n";
	}
        $str.="\t<dynamic_convert_type>" . $aa->string_to_xml($self->{dynamic_convert_type}) . "</dynamic_convert_type>\n";
        $str.="\t<dynamic_convert_desc>" . $aa->string_to_xml($self->{dynamic_convert_desc}) . "</dynamic_convert_desc>\n";
        $str.="\t<dynamic_convert_args>" . $aa->string_to_xml($self->{dynamic_convert_args}) . "</dynamic_convert_args>\n";
        $str.="\t<attributes>" . $aa->string_to_xml($self->{attributes}) . "</attributes>\n";
	$str.="</report>\n";
	if(! print $wfd $str) {
		close($wfd);
		unlink("$fp.$$");
		return "Failed to write to temporary file: $!";
	}
	close($wfd) or return "Failed to write to temporary file: $!";
	rename("$fp.$$",$fp) or return "Failed to replace file: $!";
	return undef;
}

1;
